#ifndef _MY_STACK_H_
#define _MY_STACK_H_

#include "memory.h"
#include "node.h"
#include <atomic>
#include <functional>

template<typename T>
void deleteNode(void* data) {
	delete static_cast<T*>(data);
}

struct dataToReclaim {
	void* data;
	dataToReclaim* next;
	function<void (void*)> deleter;
	
	template<typename T>
	dataToReclaim(T* d) {
		data = d;
		deleter = &deleteNode<T>;
		next = 0;
	}
	
	~dataToReclaim() {
		deleter(data);
	}
};

template<typename T>
class my_stack {
	public:
		void push(const T& data);
		shared_ptr<T> pop();
		void afficher() const;
		~my_stack();
		
	private:
		void addToReclaim(dataToReclaim* n);
		void reclaimLater(T* data);
		void deleteNodesWithNoHazards();
		static atomic<void*>& getHazardPointerForCurrentThread();
		static bool outstandingHazardPointersFor(void* p);
		
		atomic<node<T>*> head;
		static atomic<dataToReclaim*> nodesToReclaim;
};

#include "my_stack.tcc"

#endif
